#include "vector.hpp"

// конструкторы деструкторы
Vector::Vector()
{
    _v[0]=_v[1]=_v[2]=0.000001f;
}
Vector::Vector ( real_t newX, real_t newY,  real_t newZ )
{
    _v[0] = newX;
    _v[1] = newY;
    _v[2] = newZ;
};

Vector::~Vector ( void )
{
}

/// Текущее значение координат вектора                   ///
real_t *Vector::v()
{
    return _v;
}
real_t  Vector::x()
{
    return _v[0];
}
real_t  Vector::y()
{
    return _v[1];
}
real_t  Vector::z()
{
    return _v[2];
}
///  Задание новых координат вектора
void    Vector::x ( real_t newX )
{
    _v[0] = newX;
}
void    Vector::y ( real_t newY )
{
    _v[1] = newY;
}
void    Vector::z ( real_t newZ )
{
    _v[2] = newZ;
}
void    Vector::xyz ( real_t newX, real_t newY, real_t newZ )
{
    _v[0]=newX;
    _v[1]=newY;
    _v[2]=newZ;
}

void    Vector::v ( real_t *v )
{
    _v[0] = ( real_t ) v[0];
    _v[1] = ( real_t ) v[1];
    _v[2] = ( real_t ) v[2];
}

///    Длина вектора
real_t Vector::length()
{
    return sqrt ( _v[0]*_v[0] + _v[1]*_v[1] + _v[2]*_v[2] );
}

real_t Vector::length2()
{
    return _v[0]*_v[0] + _v[1]*_v[1] + _v[2]*_v[2];
}

///Скалярное произведение
real_t  Vector::mult ( Vector &vec )
{
    return ( _v[0]*vec._v[0] + _v[1]*vec._v[1] + _v[2]*vec._v[2] );
}
real_t  Vector::cos ( Vector &vec )
{
    return ( _v[0]*vec._v[0] + _v[1]*vec._v[1] + _v[2]*vec._v[2] ) /length() /vec.length();
}
///  Нормализация вектора к 1
void Vector::normalize()
{
    real_t len = 1/length();
    _v[0] *= len;
    _v[1] *= len;
    _v[2] *= len;
}
/// Нормализация к newLength
void Vector::normalize ( real_t newLength )
{
    real_t len = newLength / length();
    _v[0] *= len;
    _v[1] *= len;
    _v[2] *= len;
}

/// Сложение вычитание
Vector Vector::operator+= ( Vector const &vec )
{
    _v[0]+=vec._v[0];
    _v[1]+=vec._v[1];
    _v[2]+=vec._v[2];
    return *this;
}
Vector Vector::operator+ ( Vector const &vec )
{
    Vector result ( vec );
    result._v[0] +=_v[0];
    result._v[1] += _v[1];
    result._v[2] += _v[2];
    return result;
}

Vector Vector::operator-= ( Vector const &vec )
{
    _v[0]-= vec._v[0];
    _v[1]-= vec._v[1];
    _v[2]-= vec._v[2];

    return *this;
}
Vector Vector::operator- ( Vector const &vec )
{
    Vector result ( _v[0],_v[1],_v[2] );

    result._v[0] -= vec._v[0];
    result._v[1] -= vec._v[1];
    result._v[2] -= vec._v[2];

    return result;
}

Vector Vector::operator-()
{
    Vector result;
    
    result._v[0] =- _v[0];
    result._v[1] =- _v[1];
    result._v[2] =- _v[2];
    
    return result;
}

Vector Vector::operator+()
{
    Vector result( *this);

    return result;
}

/// Присваивание
Vector Vector::operator= ( Vector const &vec )
{
    _v[0]= vec._v[0];
    _v[1]= vec._v[1];
    _v[2]= vec._v[2];

    return vec;
}
/// Векторное произведение
Vector Vector::operator*= ( Vector const &vec )
{
    const real_t x=_v[0], y=_v[1] ,z=_v[2];

    _v[0] = ( y * vec._v[2] ) - ( z * vec._v[1] ) ;
    _v[1] = ( z * vec._v[0] ) - ( x * vec._v[2] ) ;
    _v[2] = ( x * vec._v[1] ) - ( y * vec._v[0] ) ;

    return ( *this );
}
Vector Vector::operator* ( Vector const &vec )
{
    Vector result ( vec );
    result._v[0] = ( _v[1] * vec._v[2] ) - ( _v[2] * vec._v[1] ) ;
    result._v[1] = ( _v[2] * vec._v[0] ) - ( _v[0] * vec._v[2] ) ;
    result._v[2] = ( _v[0] * vec._v[1] ) - ( _v[1] * vec._v[0] ) ;

    return result;
}
///  Произведение вектора на число
Vector Vector::operator*= ( const real_t N )
{
    _v[0]*= N;
    _v[1]*= N;
    _v[2]*= N;

    return *this;
}
Vector Vector::operator* ( const real_t N )
{
    Vector vec ( *this );

    vec._v[0] *= N;
    vec._v[1] *= N;
    vec._v[2] *= N;

    return vec;
};
//* Косинус угла между векторами
real_t cos ( Vector &vec1, Vector &vec2 )
{
    return ( vec1.x() *vec2.x() + vec1.y() *vec2.y() + vec1.z() *vec2.z() ) / ( vec1.length() * vec2.length() );
}
real_t sin ( Vector &vec1, Vector &vec2 )
{
    real_t cos = ( vec1.x() *vec2.x() + vec1.y() *vec2.y() + vec1.z() *vec2.z() ) / ( vec1.length() * vec2.length() );
    return 1 - cos * cos;
}

/// Скалярное произведение
real_t multiply ( Vector &vec1  , Vector &vec2 )
{
    return ( vec1.x() *vec2.x() + vec1.y() *vec2.y() + vec1.z() *vec2.z() );
}
